home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Texteditors / Origami / Sources / src / origami / folding.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-27  |  25.0 KB  |  898 lines

  1. /*{{{}}}*/
  2. /*{{{  #includes*/
  3. #ifdef CONFIG_H
  4. #   include "config.h"
  5. #endif
  6.  
  7. #include <sys/types.h>
  8. #include <unistd.h>
  9. #include <limits.h>
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #include <stdio.h>
  13.  
  14. #define FOLDING_C
  15. #define I_BUFFLOOP_C
  16. #define I_DISPLAY_C
  17. #define I_FINDS_C
  18. #define I_FOLDFILING_C
  19. #define I_FOLDHELP_C
  20. #define I_GETMSG_C
  21. #define I_GETTK_C
  22. #define I_KEYBOARD_C
  23. #define I_LOOP_C
  24. #define I_MAIN_C
  25. #define I_MISC_C
  26. #define I_MESSAGES_C
  27. #define I_ORIEDT_C
  28. #define I_PROMPT_C
  29. #define I_READFOLDS_C
  30. #define I_SCREEN_C
  31. #define I_STRING_C
  32. #define I_VIRTUAL_C
  33. #define I_WRITEF_C
  34.  
  35. #include "origami.h"
  36. #include <lib/ori_add_lib.h>
  37. /*}}}  */
  38.  
  39. /*{{{  variables*/
  40. public element *pick_head,*pick_tail;
  41. public unsigned char cur_dsp_line[LINELEN+1];
  42. /*}}}  */
  43.  
  44. /*{{{  normal_att*/
  45. public boolean normal_att(fold_data const * const p,boolean text)
  46. {
  47.   return
  48.    (     p->UU.U1.type==DEFAULT_TYPE
  49.      && ((p->UU.U1.contents==TEXT_CONTENTS)||text)
  50.    );
  51. }
  52. /*}}}  */
  53. /*{{{  insert_link_before*/
  54. public void insert_link_before(element * const ptr_to_new)
  55. {
  56.   element *ptr_to_prec;
  57.  
  58.   ptr_to_new->indent=bd.f.current->indent;
  59.   ori_assert(bd.f.cur_line_typ==get_linetyp(*bd.f.current),"check cur_linetyp");
  60.   if (bd.f.cur_line_typ==START_OPEN_FOLD)
  61.      ptr_to_new->indent-=bd.f.current->x.fold.UU.U1.indent;
  62.   ptr_to_prec = bd.f.current->prec;
  63.   if (bd.scr.start == bd.f.current)
  64.      bd.scr.start = ptr_to_new;
  65.   join_links(ptr_to_prec, ptr_to_new);
  66.   join_links(ptr_to_new, bd.f.current);
  67.   bd.f.current = ptr_to_new;
  68. }
  69. /*}}}  */
  70. /*{{{  copy_a_line*/
  71. public element *copy_a_line(void)
  72. {
  73.   /*{{{  check if filed fold is inside*/
  74.   if (bd.m.dialect.typ==F_C_TDS)
  75.    { element const *p;
  76.  
  77.      for (p=bd.f.current;p!=bd.f.current->next;p=move_on(p))
  78.         if (test_linetyp(*p,START_FILED))
  79.          { msg_message(M_NO_FF_COPY);
  80.            return(0);
  81.          }
  82.    }
  83.   /*}}}  */
  84.   /*{{{  copy the line*/
  85.   { element const *p;
  86.     element *q, *last, *fold_ptr, *result;
  87.     linetyp lt_last;
  88.     boolean warned;
  89.  
  90.     /*{{{  init the links*/
  91.     p = bd.f.current;
  92.     last = 0;
  93.     fold_ptr = 0; /* using other-end to store list of open folds */
  94.     result = 0;
  95.     warned=False;
  96.     /*}}}  */
  97.     while (p != bd.f.current->next)
  98.      /*{{{  handle one line of copy-region*/
  99.      { linetyp lt_new;
  100.  
  101.        /*{{{  copy the node to a new one*/
  102.        q=proc_new_element();
  103.        *q = *p;
  104.        lt_new=get_linetyp(*q);
  105.        /*}}}  */
  106.        /*{{{  copy data to new node!*/
  107.        { unsigned char const *s;
  108.  
  109.          new_data(q);   /* *q=*p destroyed the initialised data! */
  110.          s=get_data(p);
  111.          if (*s)
  112.             set_data(q,s,lt_new==NOT_FOLD);
  113.        }
  114.        /*}}}  */
  115.        /*{{{  handle the links and move on*/
  116.        q->prec = last;
  117.        if (last)
  118.         /*{{{  handle last node*/
  119.         { last->next = q;
  120.           switch(lt_last)
  121.            { case START_FOLD:
  122.              case START_FILED:
  123.                 last->x.fold.data = q;
  124.                 break;
  125.              case END_FOLD:
  126.                 q->prec = last->x.fold.other_end;
  127.                 q->prec->next = q;
  128.              default:
  129.                 break;
  130.            }
  131.         }
  132.         /*}}}  */
  133.        else
  134.         /*{{{  current line is the result!*/
  135.           result = q;
  136.         /*}}}  */
  137.        /*{{{  handle current node and move on*/
  138.        switch(lt_new)
  139.         { case START_FILED:
  140.              if (!warned)
  141.                 msg_message(M_FF_COPY);
  142.              warned=True;
  143.           case START_FOLD:
  144.              /*{{{  store fold in other-end list*/
  145.              q->x.fold.other_end = fold_ptr;
  146.              fold_ptr = q;
  147.              /*}}}  */
  148.              p=p->x.fold.data;
  149.              break;
  150.           case END_FOLD:
  151.              /*{{{  connect fold and cut other-end list*/
  152.              q->x.fold.other_end = fold_ptr;
  153.              fold_ptr = fold_ptr->x.fold.other_end;
  154.              q->x.fold.other_end->x.fold.other_end = q;
  155.              /*}}}  */
  156.           default:
  157.              p=p->next;
  158.              break;
  159.         }
  160.        /*}}}  */
  161.        /*}}}  */
  162.        /*{{{  last=current*/
  163.        lt_last=lt_new;
  164.        last=q;
  165.        /*}}}  */
  166.      }
  167.      /*}}}  */
  168.     return(result);
  169.   }
  170.   /*}}}  */
  171. }
  172. /*}}}  */
  173. /*{{{  chg_foldtype*/
  174. public boolean chg_foldtype(int const type, int const contents)
  175. {
  176.   ori_assert(bd.f.cur_line_typ==get_linetyp(*bd.f.current),"check cur_linetyp");
  177.   if (bd.f.cur_line_typ&(START_FILED|START_FOLD))
  178.    { bd.f.current->x.fold.UU.U1.type=type;
  179.      bd.f.current->x.fold.UU.U1.contents=contents;
  180.      return(False);
  181.    }
  182.   return(True);
  183. }
  184. /*}}}  */
  185. /*{{{  start_make_fold*/
  186. public void start_make_fold(sel_mod mark)
  187. {
  188.   ori_assert(bd.f.cur_line_typ==get_linetyp(*bd.f.current),"check cur_linetyp");
  189.   if
  190.    (      (bd.f.cur_line_typ=get_linetyp(*bd.f.current))
  191.         & (START_ENTER_FOLD|START_ENTER_FILED)
  192.      || (bd.scr.cursor.w - 1)/dsp.norm>=LINELEN-5
  193.    )
  194.      try_unchange();
  195.   else
  196.    { element *p;
  197.  
  198.      p=proc_new_element();
  199.      p->x.fold.close_line = bd.scr.cursor.h;
  200.      bd.e.makefold_indent = (bd.scr.cursor.w - 1)/dsp.norm;
  201.      /*{{{  set the string for p*/
  202.      { int sp_diff;
  203.  
  204.        if (bd.f.cur_line_typ&START_OPEN_FOLD)
  205.           sp_diff=bd.f.current->x.fold.UU.U1.indent;
  206.        else
  207.         { if (bd.e.makefold_indent<bd.f.current->indent)
  208.              bd.e.makefold_indent=bd.f.current->indent;
  209.           sp_diff=0;
  210.         }
  211.        spaces(line_buffer,bd.e.makefold_indent-bd.f.current->indent+sp_diff);
  212.      }
  213.      ustrcat(line_buffer,bd.f.str.open_f);
  214.      set_data(p,line_buffer,False);
  215.      /*}}}  */
  216.      undel_before(p);
  217.      bd.f.cur_line_typ=get_linetyp(*bd.f.current);
  218.      bd.m.select_mode = mark;
  219.      bd.f.select_ptr = bd.f.current;
  220.      move_down();
  221.    }
  222. }
  223. /*}}}  */
  224. /*{{{  make_fold*/
  225. public void make_fold(void)
  226. {
  227.   /*{{{  variables*/
  228.   element *p;
  229.   int open_count, ind, i;
  230.   boolean indented_enough;
  231.   int on_screen_line;
  232.   int skip_indent;
  233.   /*}}}  */
  234.  
  235.   /*{{{  check indentation and open/close-folds*/
  236.   p = bd.f.select_ptr->next;
  237.   indented_enough = True;
  238.   open_count = 0;
  239.   skip_indent=bd.f.select_ptr->indent;
  240.   while (p != bd.f.current && open_count >= 0 && indented_enough)
  241.    /*{{{  check single line*/
  242.    { linetyp lt;
  243.  
  244.      lt=get_linetyp(*p);
  245.      if (p==bd.f.tail)
  246.       { msg_message(M_NO_BACK_FOLDING);
  247.         return;
  248.       }
  249.      /*{{{  check indentation >= bd.e.makefold_indent*/
  250.      /* check not across open fold boundaries,ie no of open folds=no of end folds */
  251.      if (open_count == 0)
  252.       { if (lt&START_OPEN_FOLD)
  253.            indented_enough = (bd.e.makefold_indent <= p->indent);
  254.         else if (lt&(START_FOLD|START_FILED))
  255.            indented_enough=bd.e.makefold_indent<=(p->indent+p->x.fold.UU.U1.indent);
  256.         else if (lt&NOT_FOLD)
  257.          /*{{{  check spaces in front*/
  258.          { unsigned char *s=get_data(p);
  259.  
  260.            for (i=bd.e.makefold_indent-skip_indent;i--;)
  261.             { if (!*s)
  262.                  break;
  263.               else if (*s!=' ')
  264.                  { indented_enough=False;break; }
  265.               else
  266.                  s++;
  267.             }
  268.          }
  269.          /*}}}  */
  270.       }
  271.      /*}}}  */
  272.      if (lt&START_OPEN_FOLD)
  273.         open_count++;
  274.      else if (lt&END_FOLD)
  275.         open_count--;
  276.      p = p->next;
  277.    }
  278.    /*}}}  */
  279.   if (!(indented_enough && open_count == 0))
  280.    /*{{{  complain and return*/
  281.    { msg_message(M_FOLDERR);
  282.      return;
  283.    }
  284.    /*}}}  */
  285.   /*}}}  */
  286.   /*{{{  change indentation data of folded lines*/
  287.   p = bd.f.select_ptr->next;
  288.   ind = bd.e.makefold_indent - skip_indent;
  289.   while (p != bd.f.current)
  290.    { linetyp lt;
  291.  
  292.      if (test_linetyp(*p,START_OPEN_FOLD)) close_fold_at(p);
  293.      lt=get_linetyp(*p);
  294.      if (lt&(START_FOLD|START_FILED)) p->x.fold.UU.U1.indent -= ind;
  295.      if (lt&NOT_FOLD)
  296.         set_data(p,strsub(get_data(p),ind+1),True);
  297.      p->indent = 0;
  298.      p = p->next;
  299.    }
  300.   /*}}}  */
  301.   /*{{{  new node for close, join links and set data*/
  302.   p=proc_new_element();
  303.   insert_link_before(p);
  304.   bd.f.End_of_fold = bd.f.current;
  305.   bd.f.Line_after_fold = bd.f.End_of_fold->next;
  306.   bd.f.Start_of_fold = bd.f.select_ptr;
  307.   bd.f.Start_of_fold->x.fold.data = bd.f.Start_of_fold->next;
  308.   bd.f.Start_of_fold->x.fold.other_end = bd.f.End_of_fold;
  309.   bd.f.End_of_fold->x.fold.other_end = bd.f.Start_of_fold;
  310.   bd.f.Line_after_fold->prec = bd.f.Start_of_fold;
  311.   bd.f.Start_of_fold->next = bd.f.Line_after_fold;
  312.   set_linetyp(*bd.f.Start_of_fold,START_FOLD);
  313.   bd.f.Start_of_fold->indent = bd.e.makefold_indent - ind;
  314.   bd.f.Start_of_fold->x.fold.UU.U1.indent = ind;
  315.   set_linetyp(*bd.f.End_of_fold,END_FOLD);
  316.   bd.f.End_of_fold->indent = 0;
  317.   bd.f.current = bd.f.Start_of_fold;
  318.   bd.m.select_mode = no_selection;
  319.   upd_highlight(bd.f.select_ptr,bd.f.current,False);
  320.   bd.f.select_ptr = 0;
  321.   set_0_data(bd.f.End_of_fold);
  322.   set_0_data(bd.f.Start_of_fold);
  323.   /*}}}  */
  324.   /*{{{  update the screen*/
  325.   bd.scr.cursor.w=(bd.f.current->indent+bd.f.current->x.fold.UU.U1.indent+6)*dsp.norm-dsp.norm+1;
  326.   if ((on_screen_line=on_screen(bd.f.current)))
  327.      bd.f.current->x.fold.close_line=on_screen_line;
  328.   restore_element(bd.f.current->x.fold.close_line);
  329.   /* if on_screen and enough lines to fill screen */
  330.   /*   then restore_from(on_screen_line);         */
  331.   /*}}}  */
  332. }
  333. /*}}}  */
  334. /*{{{  remove_line*/
  335. public void remove_line(element ** const p)
  336. {
  337.   ori_assert(bd.f.cur_line_typ==get_linetyp(*bd.f.current),"check cur_linetyp");
  338.   if
  339.    (    (bd.f.cur_line_typ&(NOT_FOLD|START_FOLD|START_FILED))
  340.      && (bd.f.current != bd.f.tail)
  341.    )
  342.    { if (*p)
  343.         proc_dispose(*p);
  344.      pre_remove_line(p);
  345.      if (bd.scr.cursor.h < bd.scr.txt_size.h)
  346.         up_a_bit(bd.scr.cursor.h);
  347.      else
  348.         clrbuffline(bd.scr.txt_size.h,1);
  349.      if (bd.scr.end != bd.f.tail)
  350.       { bd.scr.end = bd.scr.end->next;
  351.         write_dsp_line(bd.scr.end, bd.scr.txt_size.h);
  352.       }
  353.      else
  354.       { bd.scr.end_level--;
  355.         whole_screen_down();
  356.       }
  357.    }
  358. }
  359. /*}}}  */
  360. /*{{{  pre_enter_fold*/
  361. private void pre_enter_fold(element * const cur)
  362. {
  363.   check_fold(cur);
  364.   bd.f.Line_after_fold->prec = bd.f.End_of_fold;
  365.   bd.f.entered++;
  366.   bd.scr.cursor.w-=(bd.f.Start_of_fold->indent+bd.f.Start_of_fold->x.fold.UU.U1.indent)*dsp.norm;
  367.   bd.f.enter_spaces+=bd.f.Start_of_fold->indent+bd.f.Start_of_fold->x.fold.UU.U1.indent;
  368.   bd.f.Start_of_fold->next = bd.f.Start_of_fold->x.fold.data;
  369.   set_linetyp(*bd.f.Start_of_fold,START_ENTER_FOLD);
  370.   bd.f.Start_of_fold->x.fold.data = bd.f.head;
  371.   bd.f.head = bd.f.Start_of_fold->prec;
  372.   bd.f.End_of_fold->x.fold.data = bd.f.tail;
  373.   bd.f.tail = bd.f.End_of_fold;
  374.   /*save indent*/
  375.   bd.f.End_of_fold->x.fold.UU.U1.indent = bd.f.Start_of_fold->indent;
  376.   bd.f.Start_of_fold->indent = 0;
  377. }
  378. /*}}}  */
  379. /*{{{  erase_current_link*/
  380. private void erase_current_link(void)
  381. {
  382.   element *prec_ptr, *p;
  383.  
  384.   if (bd.f.current != bd.f.tail)
  385.    { p = bd.f.current;
  386.      prec_ptr = p->prec;
  387.      bd.f.current = p->next;
  388.      proc_dispose(p);
  389.      join_links(prec_ptr, bd.f.current);
  390.    }
  391. }
  392. /*}}}  */
  393. /*{{{  delete_list*/
  394. public void delete_list(element *from_ptr, element * const to_ptr)
  395. {
  396.   for(;;)
  397.    { element *p;
  398.  
  399.      p = from_ptr->next;
  400.      proc_dispose(from_ptr);
  401.      if (from_ptr==to_ptr)
  402.         break;
  403.      from_ptr = p;
  404.    }
  405. }
  406. /*}}}  */
  407. /*{{{  pre_exit_fold*/
  408. public void pre_exit_fold(void)
  409. {
  410.   element *p;
  411.  
  412.   bd.f.entered--;
  413.   bd.f.Start_of_fold = bd.f.head->next;
  414.   bd.f.End_of_fold = bd.f.tail;
  415.   bd.f.Line_after_fold = bd.f.tail->next;
  416.   bd.f.tail = bd.f.End_of_fold->x.fold.data;
  417.   set_linetyp(*bd.f.Start_of_fold,START_FOLD);
  418.   bd.f.head = bd.f.Start_of_fold->x.fold.data;
  419.   bd.f.Start_of_fold->x.fold.data = bd.f.Start_of_fold->next;
  420.   bd.f.Start_of_fold->next = bd.f.Line_after_fold;
  421.   bd.f.Line_after_fold->prec = bd.f.Start_of_fold;
  422.   /*restore indent*/
  423.   bd.f.Start_of_fold->indent = bd.f.End_of_fold->x.fold.UU.U1.indent;
  424.   bd.scr.cursor.w+=(bd.f.Start_of_fold->indent+bd.f.Start_of_fold->x.fold.UU.U1.indent)*dsp.norm;
  425.   bd.f.enter_spaces-=bd.f.Start_of_fold->indent+bd.f.Start_of_fold->x.fold.UU.U1.indent;
  426.   bd.f.current = bd.f.Start_of_fold;
  427.   check_fold(bd.f.current);
  428.   for (p=bd.f.Start_of_fold->x.fold.data;;)
  429.    { switch (get_linetyp(*p))
  430.       { case END_FOLD:
  431.            break;
  432.         case START_OPEN_FOLD:
  433.            close_fold_at(p);
  434.         default:
  435.            p=p->next;
  436.            continue;
  437.       }
  438.      break;
  439.    }
  440. }
  441. /*}}}  */
  442. /*{{{  pre_top_fold*/
  443. public void pre_top_fold(void)
  444. {
  445.   while (bd.f.tail != bd.f.real_tail)
  446.      pre_exit_fold();
  447. }
  448. /*}}}  */
  449. /*{{{  pre_pre_open_fold*/
  450. private void pre_pre_open_fold(element * const q)
  451. {
  452.   check_fold(q);
  453.   bd.f.Line_after_fold->prec = bd.f.End_of_fold;
  454.   bd.f.Start_of_fold->next = bd.f.Start_of_fold->x.fold.data;
  455.   set_linetyp(*bd.f.Start_of_fold,START_OPEN_FOLD);
  456. }
  457. /*}}}  */
  458. /*{{{  pre_open_fold*/
  459. public void pre_open_fold(element * const q)
  460. {
  461.   element *p;
  462.   int i;
  463.  
  464.   pre_pre_open_fold(q);
  465.   p = bd.f.Start_of_fold;
  466.   i=p->indent+p->x.fold.UU.U1.indent;
  467.   p->indent = i;
  468.   do
  469.    { p = p->next;
  470.      p->indent += i;
  471.    }
  472.   while (p != bd.f.End_of_fold);
  473. }
  474. /*}}}  */
  475. /*{{{  enter_fold*/
  476. public void enter_fold(unsigned char const * const f_name)
  477. { element *p;
  478.  
  479.   title_op(CHGXY);
  480.   ori_assert(bd.f.cur_line_typ==get_linetyp(*bd.f.current),"check cur_linetyp");
  481.   if (!f_name && bd.f.cur_line_typ&START_FOLD)
  482.    /*{{{  normal fold -> enter*/
  483.    { bd.f.current->x.fold.close_line = bd.scr.cursor.h;
  484.      pre_enter_fold(bd.f.current);
  485.      bd.f.current = bd.f.current->next;
  486.      restore_element(DEF_CURSOR_LINE);
  487.    }
  488.    /*}}}  */
  489.   else
  490.    /*{{{  try to enter file*/
  491.    { unsigned char const *filename;
  492.      int return_line_no;
  493.  
  494.      add_edit_file((char*)0,cur_line_no(),False);
  495.      return_line_no=cur_line_no()-line_no(bd.f.head->next,bd.f.real_head);
  496.      if (!f_name && bd.f.cur_line_typ&START_FILED)
  497.       /*{{{  check filed fold*/
  498.         if (!normal_att(&(bd.f.current->x.fold),True))
  499.          /*{{{  no access*/
  500.          { msg_message(M_NO_TEXT);
  501.            return;
  502.          }
  503.          /*}}}  */
  504.         else if (bd.f.current->x.fold.data != bd.f.current->x.fold.other_end)
  505.          /*{{{  no list enter*/
  506.          { msg_message(M_NO_ENTER_LIST_FF);
  507.            return;
  508.          }
  509.          /*}}}  */
  510.         else
  511.          { unsigned char f_buff[_POSIX_PATH_MAX+1];
  512.  
  513.            ustrcpy(f_buff,get_data(bd.f.current->x.fold.other_end));
  514.            home_expand((char*)f_buff);
  515.            filename=f_buff;
  516.            if (access((char *)filename,R_OK) == -1)
  517.               if
  518.                /*{{{  can get dirname(current-file)/name)*/
  519.                (    bd.f.real_tail!=bd.f.real_head
  520.                  && join_fd(f_buff,get_data(bd.f.real_tail))
  521.                )
  522.                /*}}}  */
  523.                /*{{{  test, if existing*/
  524.                  if (access((char*)filename,R_OK)==-1)
  525.                     goto enter_cant_open;
  526.                  else
  527.                     warn_message(get_msg(F_ADD_PATH,filename));
  528.                /*}}}  */
  529.               else
  530.                /*{{{  cannot open file*/
  531.                { enter_cant_open:
  532.  
  533.                  err_message
  534.                   ( M_CANTOPEN,
  535.                     get_data(bd.f.current->x.fold.other_end)
  536.                   );
  537.                  return;
  538.                }
  539.                /*}}}  */
  540.            add_history(file_history,filename);
  541.            p = bd.f.current;
  542.            total_save((FILE*)0);
  543.            if
  544.             (    bd.m.file_changed_status!=unchanged_file
  545.               && !yes(get_msg(M_NO_SAVE_CANCEL))
  546.             )
  547.               return;
  548.            bd.scr.cursor.w = 1;
  549.            bd.f.current = p;
  550.            set_data(bd.f.current->x.fold.other_end,f_buff,False);
  551.            set_linetyp(*bd.f.current,START_FOLD); /* for copy ! */
  552.          }
  553.       /*}}}  */
  554.      else
  555.       /*{{{  get filename to push on enter-stack*/
  556.       { unsigned char buff[_POSIX_PATH_MAX+1];
  557.         unsigned char *hd;
  558.         int cursor_x_pos;
  559.  
  560.         if (f_name)
  561.          /*{{{  use given name*/
  562.          { filename=hd=buff;
  563.            ustrcpy(hd,f_name);
  564.          }
  565.          /*}}}  */
  566.         else
  567.          /*{{{  get filename from line or prompt*/
  568.          { filename=(hd=get_data(bd.f.current));
  569.            cursor_x_pos=scr2txt(bd.f.enter_spaces,bd.scr.cursor.w,filename);
  570.            /*{{{  get filename*/
  571.            /*{{{  copy pattern from current line*/
  572.            while (cursor_x_pos--)
  573.               if (*filename ) filename++; else break;
  574.            { unsigned char *d=buff;
  575.              int i=0;
  576.  
  577.              while
  578.               (   *filename
  579.                && *filename!='"'
  580.                && *filename!='\''
  581.                && *filename!=' '
  582.                && *filename!='\t'
  583.                && i<_POSIX_PATH_MAX
  584.               ) *d++ = *filename++;
  585.              *d='\0';
  586.            }
  587.            /*}}}  */
  588.            filename=buff;
  589.            if (!*filename || access((char*)filename,R_OK) == -1)
  590.               hd=fileprompt(buff);
  591.            else
  592.               add_history(file_history,filename);
  593.            if (aborted || !*filename) return;
  594.            /*}}}  */
  595.          }
  596.          /*}}}  */
  597.         find_element(cur_line_no(),bd.scr.cursor.h);
  598.         total_save((FILE*)0);
  599.         restore_element(bd.scr.cursor.h);
  600.         if
  601.          (    bd.m.file_changed_status!=unchanged_file
  602.            && !yes(get_msg(M_NO_SAVE_CANCEL))
  603.          )
  604.            return;
  605.         /*{{{  make fold for filename, after save!*/
  606.         for (;;)
  607.          { ori_assert(bd.f.cur_line_typ==get_linetyp(*bd.f.current),"check cur_linetyp");
  608.            if (bd.f.cur_line_typ&(START_ENTER_FOLD|START_ENTER_FILED))
  609.             { move_down();
  610.               bd.f.cur_line_typ=get_linetyp(*bd.f.current);
  611.             }
  612.            else
  613.               break;
  614.          }
  615.         ocl_screen_off();
  616.         start_make_fold(False);
  617.         make_fold();
  618.         ocl_screen_on();
  619.         set_data(bd.f.current,hd,False);
  620.         set_data(bd.f.current->x.fold.other_end,filename,False);
  621.         /*}}}  */
  622.       }
  623.       /*}}}  */
  624.      /*{{{  read the filed fold*/
  625.      if (!bd.m.user_view) bd.m.read_only=False;
  626.      bd.f.real_tail->x.fold.UU.U0.old_line=return_line_no;
  627.      bd.f.real_tail->x.fold.UU.U0.v_mode = bd.m.read_only;
  628.      bd.f.real_tail->x.fold.close_line = bd.scr.cursor.h;
  629.      p=copy_a_line();
  630.      bd.f.current = p;
  631.      delete_list(bd.f.head->next->next, bd.f.tail->prec);   /*except for bd.f.tail/bd.f.head*/
  632.      set_linetyp(*bd.f.current,START_ENTER_FILED);
  633.      bd.f.real_tail = bd.f.current->x.fold.data;
  634.      bd.f.current->next = bd.f.real_tail;
  635.      bd.f.head = bd.f.real_head->next;
  636.      join_links(bd.f.head, bd.f.current);
  637.      bd.f.real_head = bd.f.head;
  638.      join_links(bd.f.real_tail, bd.f.tail);
  639.      bd.f.tail = bd.f.real_tail;   /*ie file_ptr*/
  640.      bd.m.file_changed_status=unchanged_file;
  641.      title_op(CHGTITLE);
  642.      if (f_name && !(*f_name))
  643.       { gen_arg_list(bd.f.head,bd.f.tail);
  644.         bd.f.current=bd.f.head->next;
  645.       }
  646.      else
  647.       { insert_file(bd.f.tail,bd.f.current,bd.f.tail,True,bd.f.real_head,&bd.m.dir_edit,&bd.f.count_comment_line,(FILE*)0);
  648.         bd.f.current = bd.f.current->next;
  649.       }
  650.      restore_element(DEF_CURSOR_LINE);
  651. #     ifdef WINDOW_TITLE_CHANGE
  652.         wt_buff_id= -1;
  653. #     endif
  654.      /*}}}  */
  655.      call_number_macro(auto_macro);
  656.      /*{{{  current_ring_file*/
  657.      bd.e.file_no=add_edit_file((char*)get_data(bd.f.real_tail),1,True);
  658.      /*}}}  */
  659.      warn_mult_edit();
  660.    }
  661.    /*}}}  */
  662. }
  663. /*}}}  */
  664. /*{{{  exit_fold*/
  665. public void exit_fold(void)
  666. {
  667.   title_op(CHGXY);
  668.   if (bd.f.tail != bd.f.real_tail)
  669.    /*{{{  normal fold, exit it*/
  670.    { pre_exit_fold();
  671.      restore_element(bd.f.current->x.fold.close_line);
  672.      return;
  673.    }
  674.    /*}}}  */
  675.   else if (bd.f.real_tail->next == (element*)0 && !*get_data(bd.f.real_tail))
  676.    /*{{{  top, fail*/
  677.    { msg_message(M_TOP);
  678.      return;
  679.    }
  680.    /*}}}  */
  681.   else
  682.    /*{{{  save file and read surrounding file*/
  683.    { total_save((FILE*)0);
  684.      add_edit_file((char*)0,cur_line_no(),False);
  685.      if (bd.m.file_changed_status!=unchanged_file)
  686.         if (yes(get_msg(M_NO_SAVE_CANCEL)))
  687.          { bd.m.file_changed_status=unchanged_file;
  688.            title_op(CHGTITLE);
  689.          }
  690.         else
  691.            return;
  692.      if
  693.       (    !bd.f.real_tail->next
  694.         || !get_data(bd.f.real_tail->next)[0]
  695.       )
  696.       /*{{{  surrounding file is the list of edited files*/
  697.         open_arg_list();
  698.       /*}}}  */
  699.      else
  700.       /*{{{  open the normal filed fold*/
  701.       {
  702.         /*{{{  remove data of entered file*/
  703.         bd.f.real_tail = bd.f.tail->next;
  704.         bd.f.real_head = bd.f.head->prec;
  705.         delete_list(bd.f.head->next, bd.f.tail);
  706.         join_links(bd.f.head,bd.f.real_tail);
  707.         bd.f.tail = bd.f.real_tail;
  708.         bd.f.head = bd.f.real_head;
  709.         /*}}}  */
  710.         /*{{{  show new, corrected title, before reading!*/
  711.         bd.m.read_only=(bd.f.real_tail->x.fold.UU.U0.v_mode||bd.m.user_view);
  712.         title_op(CHGTITLE);
  713.         /*}}}  */
  714.         /*{{{  get file*/
  715.         { int l=bd.f.real_tail->x.fold.UU.U0.old_line;
  716.  
  717.           bd.f.real_tail->x.fold.UU.U0.old_line=0;
  718.           insert_file(bd.f.tail,bd.f.head->next,bd.f.tail,True,bd.f.real_head,&bd.m.dir_edit,&bd.f.count_comment_line,(FILE*)0);
  719.           find_element(l,bd.f.real_tail->x.fold.close_line);
  720.         }
  721.         /*}}}  */
  722.         /*{{{  update title and windowtitle*/
  723.         title_op(CHGTITLE);
  724. #        ifdef WINDOW_TITLE_CHANGE
  725.            wt_buff_id= -1;
  726. #        endif
  727.         /*}}}  */
  728.         call_number_macro(auto_macro);
  729.         /*{{{  current_ring_file*/
  730.         bd.e.file_no=add_edit_file((char*)get_data(bd.f.real_tail),1,True);
  731.         /*}}}  */
  732.       }
  733.       /*}}}  */
  734.      warn_mult_edit();
  735.    }
  736.    /*}}}  */
  737. }
  738. /*}}}  */
  739. /*{{{  open_fold*/
  740. public void open_fold(void)
  741. {
  742.   ori_assert(bd.f.cur_line_typ==get_linetyp(*bd.f.current),"check cur_linetyp");
  743.   if (!(bd.f.cur_line_typ&START_FOLD))
  744.      msg_message(M_NO_SIMPLE_FOLD);
  745.   else
  746.    { bd.f.current->x.fold.close_line = bd.scr.cursor.h;
  747.      pre_open_fold(bd.f.current);
  748.      restore_to_end(bd.scr.cursor.h);
  749.    }
  750. }
  751. /*}}}  */
  752. /*{{{  close_fold*/
  753. public void close_fold(void)
  754. {
  755.   element *p;
  756.   linetyp lt;
  757.  
  758.   p = bd.f.current;
  759.   if (test_linetyp(*p,END_FOLD))
  760.      p = p->x.fold.other_end;
  761.   while (p!=bd.f.head && (lt=get_linetyp(*p))!=START_OPEN_FOLD)
  762.    { if (lt==END_FOLD)
  763.         p=p->x.fold.other_end->prec;
  764.      else
  765.         p=p->prec;
  766.    }
  767.   if (p != bd.f.head)
  768.    { bd.f.current = p;
  769.      close_fold_at(p);
  770.      title_op(CHGXY);
  771.      restore_or_restore_to_end();
  772.    }
  773.   else if (bd.f.tail != bd.f.real_tail)
  774.      msg_message(M_USE_EXIT);
  775.   else
  776.      verbose_msg_message(M_TOP);
  777. }
  778. /*}}}  */
  779. /*{{{  unfold*/
  780. public void unfold(void)
  781. {
  782.   element *new, *p;
  783.   int ind, f_ind;
  784.  
  785.   if (!test_linetyp(*bd.f.current,START_FOLD))
  786.    /*{{{  complain*/
  787.    { msg_message(M_NO_SIMPLE_FOLD);
  788.      try_unchange();
  789.    }
  790.    /*}}}  */
  791.   else
  792.    /*{{{  do it*/
  793.    { ind = bd.f.current->indent;
  794.      f_ind = bd.f.current->x.fold.UU.U1.indent;
  795.      pre_pre_open_fold(bd.f.current);
  796.      new = bd.f.Start_of_fold->next;
  797.      p = new;
  798.      while (p != bd.f.End_of_fold)
  799.       { p->indent = ind;
  800.         if (test_linetyp(*p,NOT_FOLD))
  801.          { spaces(line_buffer,f_ind);
  802.            ustrcat(line_buffer,get_data(p));
  803.            set_data(p,line_buffer,True);
  804.          }
  805.         else
  806.            p->x.fold.UU.U1.indent += f_ind;
  807.         p = p->next;
  808.       }
  809.      if (new == bd.f.End_of_fold)
  810.         new = bd.f.Line_after_fold;
  811.      bd.f.current = bd.f.End_of_fold;
  812.      erase_current_link();
  813.      bd.f.current = bd.f.Start_of_fold;
  814.      erase_current_link();
  815.      bd.f.current = new;
  816.      if (bd.scr.start == bd.f.Start_of_fold)
  817.         restore_element(DEF_CURSOR_LINE);
  818.      else if (new == bd.f.Line_after_fold)
  819.         restore_or_restore_to_end();
  820.      else
  821.         restore_to_end(bd.scr.cursor.h);
  822.    }
  823.    /*}}}  */
  824. }
  825. /*}}}  */
  826. /*{{{  create_list*/
  827. public void create_list(void)
  828. {
  829.   element *p;
  830.  
  831.   bd.f.head=proc_new_element();
  832.   bd.f.head->prec = 0;
  833.   bd.f.tail=proc_new_element();
  834.   bd.f.tail->next = 0;
  835.   p=proc_new_element();
  836.   join_links(bd.f.head, p);
  837.   join_links(p, bd.f.tail);
  838.   set_linetyp(*p,START_ENTER_FILED);
  839.   p->x.fold.other_end = bd.f.tail;
  840.   bd.f.tail->x.fold.other_end = p;
  841.   set_linetyp(*bd.f.tail,END_FOLD);
  842.   bd.f.real_head = bd.f.head;
  843.   bd.f.real_tail = bd.f.tail;
  844.   insert_file((element *)0,p,bd.f.tail,True,bd.f.head,&bd.m.dir_edit,&bd.f.count_comment_line,(FILE*)0);
  845.   bd.f.current = p->next;
  846. }
  847. /*}}}  */
  848. /*{{{  chg_marks*/
  849. /*{{{  get_mark*/
  850. private boolean get_mark
  851.  ( unsigned char * const s,
  852.    unsigned char const * const def,
  853.    unsigned char const * const f
  854.  )
  855. {
  856.   s_readprompt(s,f,FOLD_TAG_LENGTH,no_history);
  857.   if (!aborted)
  858.      switch (s[0])
  859.       { case '\0':
  860.            ustrcpy(s,def);
  861.         default:
  862.            if (ustrlen(s)==FOLD_TAG_LENGTH)
  863.               return(False);
  864.         case ' ':
  865.         case '\t':
  866.            break;
  867.       }
  868.   msg_message(M_FAILED);
  869.   return(True);
  870. }
  871. /*}}}  */
  872.  
  873. public void chg_marks(void)
  874. {
  875.   struct f_m_str s;
  876.  
  877.   if
  878.    (   get_mark(s.open_f,(unsigned char*)BEGIN_STANDARD,(unsigned char*)STR_M_F_BEG)
  879.     || get_mark(s.file_f,(unsigned char*)FILE_STANDARD,(unsigned char*)STR_M_F_NAM)
  880.     || get_mark(s.line_f,(unsigned char*)LINE_STANDARD,(unsigned char*)STR_M_F_LIN)
  881.     || get_mark(s.close_f,(unsigned char*)END_STANDARD,(unsigned char*)STR_M_F_END)
  882.     || (    !ustrcmp(bd.f.str.open_f,s.open_f)
  883.          && !ustrcmp(bd.f.str.close_f,s.close_f)
  884.          && !ustrcmp(bd.f.str.file_f,s.file_f)
  885.          && !ustrcmp(bd.f.str.line_f,s.line_f)
  886.        )
  887.    )
  888.      try_unchange();
  889.   else
  890.    /*{{{  change the marks*/
  891.    { set_fold_mark_dsp_length(&s);
  892.      init_buffer.f.str=bd.f.str=s;
  893.      restore(1);
  894.    }
  895.    /*}}}  */
  896. }
  897. /*}}}  */
  898.